<template>
  <div class="editor-container">
    <!-- 左侧面板区域 -->
    <div class="editor-left">
      <!-- 组件面板 -->
      <ComponentPanel class="panel-section" />
      
      <!-- 数据池面板 -->
      <DataPoolPanel class="panel-section" />
    </div>
    
    <!-- 中间画布区域 -->
    <div class="editor-center">
      <!-- 顶部工具栏 -->
      <div class="toolbar">
        <div class="toolbar-item" @click="undo" title="撤销">
          <span>↩️ 撤销</span>
        </div>
        <div class="toolbar-item" @click="redo" title="重做">
          <span>↪️ 重做</span>
        </div>
        <div class="toolbar-item" @click="exportPage" title="导出JSON">
          <span>📤 导出</span>
        </div>
        <div class="toolbar-item" @click="importPage" title="导入JSON">
          <span>📥 导入</span>
        </div>
        <div class="toolbar-item" @click="previewPage" title="预览页面">
          <span>👁️ 预览</span>
        </div>
        <div class="toolbar-item" @click="clearPage" title="清空页面">
          <span>🗑️ 清空</span>
        </div>
      </div>
      
      <!-- 设计画布 -->
      <div 
        class="design-canvas"
        @dragover="onDragOver"
        @drop="onDrop"
        @click="onCanvasClick"
      >
        <!-- 渲染组件列表 -->
        <template v-if="pageConfig.components.length > 0">
          <ComponentRenderer 
            v-for="(component, index) in pageConfig.components" 
            :key="component.id"
            :component="component"
            :is-selected="component.id === selectedComponentId"
            @select="selectComponent"
            @move="moveComponent"
          />
        </template>
        
        <!-- 空状态提示 -->
        <div v-else class="empty-tip">
          <p>从左侧拖拽组件到此处开始设计</p>
        </div>
        
        <!-- 辅助线 -->
        <div v-show="showHorizontalLine" class="guide-line horizontal" :style="{ top: horizontalLinePos + 'px' }"></div>
        <div v-show="showVerticalLine" class="guide-line vertical" :style="{ left: verticalLinePos + 'px' }"></div>
      </div>
    </div>
    
    <!-- 右侧属性面板 -->
    <PropertyPanel class="editor-right" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { usePageStore } from '@/stores/page'
import ComponentPanel from './components/ComponentPanel.vue'
import PropertyPanel from './components/PropertyPanel.vue'
import ComponentRenderer from './components/ComponentRenderer.vue'
import DataPoolPanel from './components/DataPoolPanel.vue'

const router = useRouter()
const pageStore = usePageStore()

// 获取页面配置和选中组件ID
const pageConfig = computed(() => pageStore.pageConfig)
const selectedComponentId = computed(() => pageStore.selectedComponentId)

// 辅助线状态
const showHorizontalLine = ref(false)
const showVerticalLine = ref(false)
const horizontalLinePos = ref(0)
const verticalLinePos = ref(0)

// 吸附阈值（像素）
const SNAP_THRESHOLD = 10

// 撤销操作
const undo = () => {
  pageStore.undo()
}

// 重做操作
const redo = () => {
  pageStore.redo()
}

// 导出页面配置为JSON
const exportPage = () => {
  const jsonStr = pageStore.exportJSON()
  const blob = new Blob([jsonStr], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  
  // 创建下载链接并触发下载
  const a = document.createElement('a')
  a.href = url
  a.download = `${pageConfig.value.title || '未命名页面'}.json`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

// 导入页面配置
const importPage = () => {
  // 创建文件输入框
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = 'application/json'
  
  input.onchange = (event) => {
    const file = (event.target as HTMLInputElement).files?.[0]
    if (!file) return
    
    const reader = new FileReader()
    reader.onload = (e) => {
      try {
        const jsonStr = e.target?.result as string
        const success = pageStore.importJSON(jsonStr)
        
        if (success) {
          alert('导入成功')
        } else {
          alert('导入失败：无效的JSON格式')
        }
      } catch (error) {
        console.error('导入失败:', error)
        alert('导入失败：无效的JSON格式')
      }
    }
    reader.readAsText(file)
  }
  
  input.click()
}

// 预览页面
const previewPage = () => {
  // 将当前页面配置保存到localStorage
  localStorage.setItem('previewPageConfig', pageStore.exportJSON())
  
  // 保存数据池配置到本地存储
  const dataPoolStore = useDataPoolStore()
  localStorage.setItem('previewDataPool', dataPoolStore.exportJSON())
  
  // 跳转到预览页面
  router.push('/preview')
}

// 清空页面
const clearPage = () => {
  if (confirm('确定要清空当前页面吗？此操作不可恢复。')) {
    pageStore.pageConfig.components = []
    pageStore.selectComponent(null)
    pageStore.saveHistory()
  }
}

// 画布点击事件
const onCanvasClick = (event: MouseEvent) => {
  // 如果点击的是画布本身，取消组件选中状态
  if (event.target === event.currentTarget) {
    pageStore.selectComponent(null)
  }
}

// 拖拽经过画布事件
const onDragOver = (event: DragEvent) => {
  event.preventDefault()
  
  // 显示放置指示
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy'
  }
  
  // 处理辅助线和吸附效果
  handleGuidelines(event)
}

// 处理辅助线和吸附效果
const handleGuidelines = (event: DragEvent) => {
  // 获取鼠标位置
  const mouseX = event.clientX
  const mouseY = event.clientY
  
  // 获取画布位置信息
  const canvas = event.currentTarget as HTMLElement
  const canvasRect = canvas.getBoundingClientRect()
  
  // 计算相对于画布的位置
  const relativeX = mouseX - canvasRect.left
  const relativeY = mouseY - canvasRect.top
  
  // 初始化最小距离和最近的对齐位置
  let minHorizontalDist = SNAP_THRESHOLD
  let minVerticalDist = SNAP_THRESHOLD
  let closestHorizontalPos = -1
  let closestVerticalPos = -1
  
  // 遍历所有组件，查找可能的对齐位置
  pageConfig.value.components.forEach(component => {
    // 获取组件元素
    const el = document.querySelector(`[data-component-id="${component.id}"]`) as HTMLElement
    if (!el) return
    
    const rect = el.getBoundingClientRect()
    const compTop = rect.top - canvasRect.top
    const compLeft = rect.left - canvasRect.left
    const compRight = compLeft + rect.width
    const compBottom = compTop + rect.height
    
    // 检查水平对齐（顶部、中部、底部）
    const distances = [
      { pos: compTop, dist: Math.abs(relativeY - compTop) },
      { pos: compTop + rect.height / 2, dist: Math.abs(relativeY - (compTop + rect.height / 2)) },
      { pos: compBottom, dist: Math.abs(relativeY - compBottom) }
    ]
    
    distances.forEach(({ pos, dist }) => {
      if (dist < minHorizontalDist) {
        minHorizontalDist = dist
        closestHorizontalPos = pos
      }
    })
    
    // 检查垂直对齐（左侧、中部、右侧）
    const vDistances = [
      { pos: compLeft, dist: Math.abs(relativeX - compLeft) },
      { pos: compLeft + rect.width / 2, dist: Math.abs(relativeX - (compLeft + rect.width / 2)) },
      { pos: compRight, dist: Math.abs(relativeX - compRight) }
    ]
    
    vDistances.forEach(({ pos, dist }) => {
      if (dist < minVerticalDist) {
        minVerticalDist = dist
        closestVerticalPos = pos
      }
    })
  })
  
  // 显示或隐藏辅助线
  if (closestHorizontalPos >= 0) {
    showHorizontalLine.value = true
    horizontalLinePos.value = closestHorizontalPos
  } else {
    showHorizontalLine.value = false
  }
  
  if (closestVerticalPos >= 0) {
    showVerticalLine.value = true
    verticalLinePos.value = closestVerticalPos
  } else {
    showVerticalLine.value = false
  }
}

// 放置组件事件
const onDrop = (event: DragEvent) => {
  event.preventDefault()
  
  // 隐藏辅助线
  showHorizontalLine.value = false
  showVerticalLine.value = false
  
  if (!event.dataTransfer) return
  
  try {
    // 获取拖拽的组件数据
    const jsonStr = event.dataTransfer.getData('application/json')
    if (!jsonStr) return
    
    const componentConfig = JSON.parse(jsonStr)
    
    // 获取画布位置信息
    const canvas = event.currentTarget as HTMLElement
    const canvasRect = canvas.getBoundingClientRect()
    
    // 计算放置位置（相对于画布）
    let dropX = event.clientX - canvasRect.left
    let dropY = event.clientY - canvasRect.top
    
    // 应用吸附效果
    if (showHorizontalLine.value) {
      dropY = horizontalLinePos.value
    }
    
    if (showVerticalLine.value) {
      dropX = verticalLinePos.value
    }
    
    // 更新组件位置
    componentConfig.style.position = 'absolute'
    componentConfig.style.top = `${dropY}px`
    componentConfig.style.left = `${dropX}px`
    
    // 添加组件到页面
    pageStore.addComponent(componentConfig)
  } catch (error) {
    console.error('放置组件失败:', error)
  }
}

// 选择组件
const selectComponent = (id: string) => {
  pageStore.selectComponent(id)
}

// 移动组件
const moveComponent = (id: string, deltaX: number, deltaY: number) => {
  const component = pageStore.selectedComponent
  if (!component) return
  
  // 更新组件位置
  const currentTop = parseFloat(component.style.top as string) || 0
  const currentLeft = parseFloat(component.style.left as string) || 0
  
  pageStore.updateComponent(id, {
    style: {
      top: `${currentTop + deltaY}px`,
      left: `${currentLeft + deltaX}px`
    }
  })
}

// 监听键盘事件（用于删除组件等）
const handleKeyDown = (event: KeyboardEvent) => {
  // 删除选中的组件
  if (event.key === 'Delete' && selectedComponentId.value) {
    pageStore.removeComponent(selectedComponentId.value)
  }
  
  // 撤销/重做快捷键
  if (event.ctrlKey || event.metaKey) {
    if (event.key === 'z') {
      if (event.shiftKey) {
        // Ctrl+Shift+Z 重做
        redo()
      } else {
        // Ctrl+Z 撤销
        undo()
      }
      event.preventDefault()
    } else if (event.key === 'y') {
      // Ctrl+Y 重做
      redo()
      event.preventDefault()
    }
  }
}

// 组件挂载和卸载时添加/移除事件监听
onMounted(() => {
  window.addEventListener('keydown', handleKeyDown)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
})
</script>

<style lang="scss" scoped>
.editor-container {
  display: flex;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  
  .editor-left {
    width: 250px;
    height: 100%;
    flex-shrink: 0;
  }
  
  .editor-center {
    flex: 1;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    
    .toolbar {
      height: 50px;
      flex-shrink: 0;
    }
    
    .design-canvas {
      flex: 1;
      position: relative;
      overflow: auto;
      background-color: #f5f5f5;
      background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
                        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
      background-size: 20px 20px;
      background-position: 0 0, 10px 10px;
      
      .empty-tip {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;
        color: #999;
        font-size: 16px;
      }
      
      .guide-line {
        position: absolute;
        background-color: #409eff;
        z-index: 9999;
        pointer-events: none;
        
        &.horizontal {
          height: 1px;
          width: 100%;
        }
        
        &.vertical {
          width: 1px;
          height: 100%;
        }
      }
    }
  }
  
  .editor-right {
    width: 300px;
    height: 100%;
    flex-shrink: 0;
  }
}

</style>